#include "interrupts.h"
#include "kbd.h"
#include "pic.h"
#include "kernel.h"
#include "stdio.h"

IDTR idtr;
IDT_entry idt[MAX_INTERRUPTS];

/* table of the body of the interrupt handlers */
interrupt_t interrupt_handlers[MAX_INTERRUPTS];

void handle_interrupt(registers r) {
	interrupt_handlers[r.int_no]();
}

void install_handler(int n, dword handler) {
	idt[n].base_lo = handler & 0xFFFF;
	idt[n].base_hi = (handler >> 16) & 0xFFFF;
}

void dummy_handler() {
	return;
}

void register_isr(int no, interrupt_t i) {
	interrupt_handlers[no] = i;
}

static void init_IDT() {
	idtr.limit = sizeof(IDT_entry) * MAX_INTERRUPTS - 1;
	idtr.offset = (int)(&idt) | 0x00100000;
	load_IDT(((u32)&idtr));
}

// various handlers for processor exceptions
void divide_error() {
  kprintf("Division error\n");
  //while(1);
}

void overflow() {
  kprintf("Overflow error\n");
  //while(1);
}

void double_fault() {
  kprintf("Double Fault!!\n");
}

void invalid_tss() {
  kprintf("Invalid TSS\n");
}

void stack_exception() {
  kprintf("Stack exception\n");
}

void triple_fault() {
  kprintf("Triple Fault!!!\n");
  while(1);
}

void init_interrupts() {
  int i;

  init_IDT();

  for(i = 0; i < MAX_INTERRUPTS; ++i) {
    idt[i].zero = 0;
    idt[i].flags = INTERRUPT_FLAGS;
    idt[i].selector = KERNEL_CS;
    interrupt_handlers[i] = dummy_handler;
  }
  
  // setup exception handlers
  register_isr(DIVIDE_ERROR, divide_error);
  register_isr(OVERFLOW, overflow);
  register_isr(DOUBLE_FAULT, double_fault);
  register_isr(INVALID_TSS, invalid_tss);
  register_isr(STACK_EXCEPTION, stack_exception);
  register_isr(TRIPLE_FAULT, triple_fault);

  
  install_handler(0, (dword)isr_stub_0);
  install_handler(1, (dword)isr_stub_1);
  install_handler(2, (dword)isr_stub_2);
  install_handler(3, (dword)isr_stub_3);
  install_handler(4, (dword)isr_stub_4);
  install_handler(5, (dword)isr_stub_5);
  install_handler(6, (dword)isr_stub_6);
  install_handler(7, (dword)isr_stub_7);
  install_handler(8, (dword)isr_stub_8);
  install_handler(9, (dword)isr_stub_9);
  install_handler(10, (dword)isr_stub_10);
  install_handler(11, (dword)isr_stub_11);
  install_handler(12, (dword)isr_stub_12);
  install_handler(13, (dword)isr_stub_13);
  install_handler(14, (dword)isr_stub_14);
  install_handler(15, (dword)isr_stub_15);
  install_handler(16, (dword)isr_stub_16);
  install_handler(17, (dword)isr_stub_17);
  install_handler(18, (dword)isr_stub_18);
  install_handler(19, (dword)isr_stub_19);
  install_handler(20, (dword)isr_stub_20);
  install_handler(21, (dword)isr_stub_21);
  install_handler(22, (dword)isr_stub_22);
  install_handler(23, (dword)isr_stub_23);
  install_handler(24, (dword)isr_stub_24);
  install_handler(25, (dword)isr_stub_25);
  install_handler(26, (dword)isr_stub_26);
  install_handler(27, (dword)isr_stub_27);
  install_handler(28, (dword)isr_stub_28);
  install_handler(29, (dword)isr_stub_29);
  install_handler(30, (dword)isr_stub_30);
  install_handler(31, (dword)isr_stub_31);
  install_handler(32, (dword)isr_stub_32);
  install_handler(33, (dword)isr_stub_33);
  install_handler(34, (dword)isr_stub_34);
  install_handler(35, (dword)isr_stub_35);
  install_handler(36, (dword)isr_stub_36);
  install_handler(37, (dword)isr_stub_37);
  install_handler(38, (dword)isr_stub_38);
  install_handler(39, (dword)isr_stub_39);
  install_handler(40, (dword)isr_stub_40);
  install_handler(41, (dword)isr_stub_41);
  install_handler(42, (dword)isr_stub_42);
  install_handler(43, (dword)isr_stub_43);
  install_handler(44, (dword)isr_stub_44);
  install_handler(45, (dword)isr_stub_45);
  install_handler(46, (dword)isr_stub_46);
  install_handler(47, (dword)isr_stub_47);		
}
